﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace Soft.Xml
{
    [Serializable]
    public class BaseXml : XmlDocument
    {


        public BaseXml()
        {
            this.IgnoreIOError = false;
            this.Initialize();
        }


        public BaseXml(XmlImplementation imp) : base(imp)
        {
            this.Initialize();
        }


        public BaseXml(XmlNameTable nt) : base(nt)
        {
            this.Initialize();
        }


        /// <summary>
        /// 初始化
        /// </summary>
        protected virtual void Initialize()
        {
        }


        /// <summary>
        /// 获取Element的值
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="name"></param>
        /// <param name="autoCreate"></param>
        /// <returns></returns>
        public XmlElement GetElement(XmlNode parent, string name, bool autoCreate = true)
        {
            if (parent == null)
            {
                throw new ArgumentNullException("parent");
            }
            XmlElement xmlElement = (XmlElement)parent.SelectSingleNode(name);
            if (xmlElement == null && autoCreate)
            {
                xmlElement = base.CreateElement(name);
                parent.AppendChild(xmlElement);
            }
            return xmlElement;
        }


        /// <summary>
        /// 获取Element的值
        /// </summary>
        /// <param name="path"></param>
        /// <param name="autoCreate"></param>
        /// <returns></returns>
        public XmlElement GetElement(string path, bool autoCreate = true)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }
            XmlElement xmlElement = (XmlElement)base.SelectSingleNode(path);
            if (xmlElement == null && autoCreate)
            {
                string[] array = path.Split(new char[]
                {
                    '/'
                }, StringSplitOptions.RemoveEmptyEntries);
                XmlNode xmlNode = this;
                foreach (string name in array)
                {
                    xmlNode = this.GetElement(xmlNode, name, true);
                }
                xmlElement = (XmlElement)xmlNode;
            }
            return xmlElement;
        }


        /// <summary>
        /// 设置Element元素的值
        /// </summary>
        /// <param name="element"></param>
        /// <param name="value"></param>
        public void SetElementValue(XmlElement element, string value)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }
            element.InnerText = value;
        }


        /// <summary>
        /// 设置Element元素的值
        /// </summary>
        /// <param name="path"></param>
        /// <param name="value"></param>
        public void SetElementValue(string path, string value)
        {
            XmlElement element = this.GetElement(path, true);
            if (element == null)
            {
                throw new KeyNotFoundException("XML文本中路径 " + path + " 不存在。");
            }
            element.InnerText = value;
        }


        /// <summary>
        /// 获取Element元素的值
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        public string GetElementValue(XmlElement element)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }
            return element.InnerText;
        }


        /// <summary>
        /// 获取Element元素的值
        /// </summary>
        /// <param name="element"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public string GetElementValue(XmlElement element, string defValue)
        {
            if (element == null)
            {
                return defValue;
            }
            return this.GetElementValue(element);
        }


        /// <summary>
        /// 获取Element元素的值
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public string GetElementValue(string path)
        {
            XmlElement xmlElement = (XmlElement)base.SelectSingleNode(path);
            if (xmlElement != null)
            {
                return this.GetElementValue(xmlElement);
            }
            return "";
        }

     
        /// <summary>
        /// 获取Element元素的值
        /// </summary>
        /// <param name="path"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public string GetElementValue(string path, string defValue)
        {
            XmlElement xmlElement = (XmlElement)base.SelectSingleNode(path);
            if (xmlElement != null)
            {
                return this.GetElementValue(xmlElement);
            }
            return defValue;
        }


        /// <summary>
        /// 是否忽略错误
        /// </summary>
        public bool IgnoreIOError { get; set; }


        /// <summary>
        /// 加载Xml文件
        /// </summary>
        /// <param name="xml"></param>
        public override void LoadXml(string xml)
        {
            try
            {
                base.LoadXml(xml);
            }
            catch (Exception ex)
            {
                if (!this.IgnoreIOError)
                {
                    throw ex;
                }
            }
            this.Initialize();
        }


        /// <summary>
        /// 加载文件
        /// </summary>
        /// <param name="filename"></param>
        public override void Load(string filename)
        {
            try
            {
                base.Load(filename);
            }
            catch (Exception ex)
            {
                if (!this.IgnoreIOError)
                {
                    throw ex;
                }
            }
            this.Initialize();
        }


        /// <summary>
        /// 加载文件
        /// </summary>
        /// <param name="inStream"></param>
        public override void Load(Stream inStream)
        {
            try
            {
                base.Load(inStream);
            }
            catch (Exception ex)
            {
                if (!this.IgnoreIOError)
                {
                    throw ex;
                }
            }
            this.Initialize();
        }


        /// <summary>
        /// 加载文件
        /// </summary>
        /// <param name="txtReader"></param>
        public override void Load(TextReader txtReader)
        {
            try
            {
                base.Load(txtReader);
            }
            catch (Exception ex)
            {
                if (!this.IgnoreIOError)
                {
                    throw ex;
                }
            }
            this.Initialize();
        }


        /// <summary>
        /// 加载文件
        /// </summary>
        /// <param name="reader"></param>
        public override void Load(XmlReader reader)
        {
            try
            {
                base.Load(reader);
            }
            catch (Exception ex)
            {
                if (!this.IgnoreIOError)
                {
                    throw ex;
                }
            }
            this.Initialize();
        }


    }
}
